using System;
using System.Diagnostics.Contracts;
using System.ServiceModel.Syndication;
using OpenWaves.Caching;

namespace OpenWaves.Syndication
{
    public class CachingSyndicationFeedLoader : ISyndicationFeedLoader
    {
        private readonly ISyndicationFeedLoader innerLoader;
        private readonly IConcurrentCache<SyndicationFeed> cache;
        private readonly TimeSpan expiration;

        public CachingSyndicationFeedLoader(IConcurrentCache<SyndicationFeed> cache)
            : this(new SyndicationFeedLoader(), cache, TimeSpan.FromHours(1))
        {
        }

        public CachingSyndicationFeedLoader(IConcurrentCache<SyndicationFeed> cache, TimeSpan expiration) : this(new SyndicationFeedLoader(), cache, expiration)
        {
        }

        public CachingSyndicationFeedLoader(ISyndicationFeedLoader innerLoader, IConcurrentCache<SyndicationFeed> cache, TimeSpan expiration)
        {
            Contract.Requires<ArgumentNullException>(innerLoader != null);
            Contract.Requires<ArgumentNullException>(cache != null);
            Contract.Requires<ArgumentOutOfRangeException>(expiration >= TimeSpan.Zero);

            this.innerLoader = innerLoader;
            this.cache = cache;
            this.expiration = expiration;
        }

        public SyndicationFeed LoadFeed(Url url)
        {
            return this.cache.GetOrCreate(url.ToString(), () =>
                                                              {
                                                                  var feed = this.innerLoader.LoadFeed(url);
                                                                  return CacheEntry.FromValue(feed, this.expiration);
                                                              });
        }
    }
}